package com.game.logic.items.prop;

import akka.actor.ActorRef;
import com.coment.cfg.luban.Tables;
import com.coment.cfg.luban.constant.AIDCFG;
import com.coment.cfg.luban.items.PropCfg;
import com.coment.game.fight.Attribute;
import com.coment.game.fight.AttributeManagerLogic;
import com.coment.game.fight.Attrs;
import com.coment.message.roles.ObtainExp;
import com.coment.po.UserProp;
import com.game.dao.user.UserDao;
import com.game.dao.user.UserPlayInfoDao;
import com.game.dao.user.prop.UserPropDao;
import com.game.dao.user.prop.UserRolesPropDao;
import com.game.dao.user.roles.RolesDao;
import com.game.framework.ActorManager;
import com.game.logic.fighting.actor.RolesActor;
import com.game.logic.fighting.attrs.AttrsManagement;
import com.game.logic.items.prop.message.UserPropList;
import com.xs.action.exection.ActionException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/// 5.道具服务
@Slf4j
@Service
public class PropService {
    private final UserDao userDao;
    private final UserPropDao userPropDao;
    private final AttrsManagement attrsManagement;
    private final UserPlayInfoDao userPlayInfoDao;

    public PropService(UserDao userDao, RolesDao rolesDao, UserPropDao userPropDao, UserRolesPropDao userRolesPropDao, AttrsManagement attrsManagement, UserPlayInfoDao userPlayInfoDao) {
        this.userDao = userDao;
        this.userPropDao = userPropDao;
        this.attrsManagement = attrsManagement;
        this.userPlayInfoDao = userPlayInfoDao;
    }


    /// 升级/获取 道具
    public UserProp obtainOrUpgrade(
            Integer userInfoId,
            Integer propId
    ) {
        if (!userDao.existsById(userInfoId)) throw new ActionException("用户%s不存在".formatted(userInfoId));

        UserProp userProp = userPropDao.findById(Objects.hash(userInfoId, propId)).orElseGet(() -> userPropDao.save(new UserProp(userInfoId, propId)));

        PropCfg propCfg = Tables.cfg.get_tbpropcfg().get(propId);
        if (propCfg == null) {
            throw new ActionException("找不到道具配置，道具ID: " + propId);
        }

        Attrs attrs = AttributeManagerLogic.obtainCfgAttrs(propCfg);
        attrs.replaceAll((k, v) -> v * userProp.number);
        log.debug("玩家{}获取道具{},道具属性为{}", userInfoId, propId, Attribute.getLogInfo(attrs));

        if (propCfg.autoSnap == 1) {
            userProp.useCount++;

            if (userProp.useCount > propCfg.usageLimit) {
                throw new ActionException("道具%s达到使用上限%s".formatted(propId, propCfg.usageLimit));
            }


            Double exp = attrs.get(AIDCFG.exp);
            if (exp != 0) {
                String recentlyPlayedRolesId = userPlayInfoDao.findByUserInfoIdOrCreate(userInfoId).recentlyPlayedRolesId;
                ActorManager.getActor(RolesActor.class, recentlyPlayedRolesId).tell(
                        new ObtainExp(exp),
                        ActorRef.noSender()
                );
            }
        } else {
            userProp.number += 1;
            if (userProp.number > propCfg.usageLimit) {
                throw new ActionException("道具%s拥有数量达到上限%s".formatted(propId, propCfg.usageLimit));
            }
        }

        Attrs bestNewAttrsOfProp = new Attrs();
        for (Map.Entry<Integer, Double> attrsEntry : attrs.entrySet()) {
            Integer id = attrsEntry.getKey();
            Double value = attrsEntry.getValue();
            bestNewAttrsOfProp.put(id, value * userProp.number);
        }

        // 记录全局属性
        attrsManagement.logAttrsGlobal(userInfoId, bestNewAttrsOfProp, "道具", propId);
        userPropDao.save(userProp);

        return userProp;
    }


    public List<UserProp> obtainOrUpgrade(Integer userInfoId, Integer... groups) {
        List<Integer> groupList = Arrays.asList(groups);
        return Tables.cfg.get_tbpropcfg().getDataList().stream()
                .filter(propCfg -> groupList.contains(propCfg.group))
                .map(propCfg -> obtainOrUpgrade(userInfoId, propCfg.id))
                .toList();
    }

    /// 查看用户道具
    public UserPropList selectAll(Integer userInfoId, Integer... groups) {
        if (!userDao.existsById(userInfoId)) throw new ActionException("用户%s不存在".formatted(userInfoId));
        UserPropList userPropList = new UserPropList();
        ArrayList<UserProp> userProps = new ArrayList<>();

        // groups 转 list
        List<Integer> groupList = Arrays.asList(groups);

        List<UserProp> propList = userPropDao.searchAllByUserInfoId(userInfoId);
        propList.stream().filter(userProp -> groupList.contains(Tables.cfg.get_tbpropcfg().get(userProp.propId).group))
                .forEach(userProps::add);
        userPropList.setUserPropList(userProps);
        return userPropList;
    }
}